package com.sharemarking.wa.platform.utils;

import com.github.binarywang.wxpay.bean.request.WxEntPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxEntPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.service.WxPayService;
import me.chanjar.weixin.common.exception.WxErrorException;

import java.io.File;
import java.security.MessageDigest;
import java.util.*;

/**
 * 微信支付
 *
 * @author kj
 * @date 2017/12/5
 */
public class WechatPay {

    /**
     * 统一下单:
     * (详见http://com.github.binarywang.wechat_h5.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
     * 在发起微信支付前，需要调用统一下单接口，获取"预支付交易会话标识"
     * 接口地址：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3
     *
     * 请求对象，注意一些参数如appid、mchid等不用设置，方法内会自动从配置对象中获取到（前提是对应配置中已经设置）
     * @param wxPayService WxPayService
     * @param  orderRequest WxPayUnifiedOrderRequest
     * @return WxPayUnifiedOrderResult
     * @throws WxErrorException  WxErrorException
     */
    public static WxPayUnifiedOrderResult unifiedOrder(WxPayService wxPayService,
                                                WxPayUnifiedOrderRequest orderRequest) throws WxErrorException {
    	return wxPayService.unifiedOrder(orderRequest);
    }

    /**
     * 微信退款申请
     * @param refundRequest
     * @param wxPayService
     * @return
     * @throws WxErrorException
     */
    public static WxPayRefundResult refund(WxPayService wxPayService,
                                           WxPayRefundRequest refundRequest) throws WxErrorException {
        return wxPayService.refund(refundRequest);
    }

    /**
     * 微信公众号h5支付
     * @param wxPayService
     * @param orderRequest
     * @return
     * @throws WxErrorException
     */
    public static Map<String, String> getPayInfo(WxPayService wxPayService,
                                                       WxPayUnifiedOrderRequest orderRequest) throws WxErrorException {
        return wxPayService.getPayInfo(orderRequest);
    }

    /**
     * <pre>
     * 企业付款业务是基于微信支付商户平台的资金管理能力，为了协助商户方便地实现企业向个人付款，针对部分有开发能力的商户，提供通过API完成企业付款的功能。
     * 比如目前的保险行业向客户退保、给付、理赔。
     * 企业付款将使用商户的可用余额，需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。
     * 注意：与商户微信支付收款资金并非同一账户，需要单独充值。
     * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
     * 接口链接：https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
     * </pre>
     *
     * @param request 请求对象
     */
    public static WxEntPayResult entPay(WxPayService wxPayService,WxEntPayRequest request) throws WxErrorException{
        return wxPayService.entPay(request);
    }

    /**
     * <pre>
     * 扫码支付模式二生成二维码的方法
     * 对应链接格式：weixin：//wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
     * 该模式链接较短，生成的二维码打印到结账小票上的识别率较高。
     * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
     * </pre>
     *
     * @param codeUrl    微信返回的交易会话的二维码链接
     * @param logoFile   商户logo图片的文件对象，可以为空
     * @param sideLength 要生成的二维码的边长，如果为空，则取默认值400
     * @return 生成的二维码的字节数组
     */
    public static byte[] createScanPayQrcodeMode2(WxPayService wxPayService,String codeUrl, File logoFile, Integer sideLength) {
      return wxPayService.createScanPayQrcodeMode2(codeUrl, logoFile, sideLength);
    }

    /**
     * 产生length长度的随机字符串
     * @param length int
     * @return String
     */
    public static String createNoncestr(int length) {
        String dict = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int r = random.nextInt(dict.length());
            sb.append(dict.charAt(r));
        }
        return sb.toString();
    }

    /**
     * 将字符串进行md5加密
     * @return
     */
    public static String getSign(Map<String, Object> params,String mchKey) {
        Set<String> keySet = params.keySet();
        List<String> keyList = new ArrayList<String>(keySet);
        Collections.sort(keyList);
        String data = "";
        for (String paramKey : keyList) {
            data += paramKey + "=" + params.get(paramKey).toString() + "&";
        }
        data += "key=" + mchKey;
        String hex = WXMD5.MD5Encode(data).toUpperCase();
        return hex;
    }

    /**
     * 微信md5加密方法
     * @author king
     */
    public static class WXMD5 {
        private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
                "8", "9", "a", "b", "c", "d", "e", "f"};
        /**
         * 转换字节数组为16进制字串
         * @param b 字节数组
         * @return 16进制字串
         */
        public static String byteArrayToHexString(byte[] b) {
            StringBuilder resultSb = new StringBuilder();
            for (byte aB : b) {
                resultSb.append(byteToHexString(aB));
            }
            return resultSb.toString();
        }
        /**
         * 转换byte到16进制
         * @param b 要转换的byte
         * @return 16进制格式
         */
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0) {
                n = 256 + n;
            }
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }

        /**
         * MD5编码
         * @param origin 原始字符串
         * @return 经过MD5加密之后的结果
         */
        public static String MD5Encode(String origin) {
            String resultString = null;
            try {
                resultString = origin;
                MessageDigest md = MessageDigest.getInstance("MD5");
                resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8")));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return resultString;
        }

    }

}
